home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / osrc.arc / AX25CMD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-16  |  10.3 KB  |  510 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "timer.h"
  5. #include "proc.h"
  6. #include "iface.h"
  7. #include "ax25.h"
  8. #include "lapb.h"
  9. #include "cmdparse.h"
  10. #include "socket.h"
  11. #include "ax25tnc.h"
  12. #include "session.h"
  13.  
  14.  
  15. extern char Notval[];
  16. extern int Digipeat;
  17. extern int16 T3init,N2,Maxframe,Paclen,Pthresh,Axwindow,Axirtt,Axversion;
  18. extern int errno;
  19.  
  20. void ax_in();
  21. static int domycall(),dodigipeat(),doaxirtt(),doaxstat(),dot3(),domaxframe(),
  22.     doaxwindow(),dopaclen(),don2(),doaxreset(),dopthresh(),doaxroute(),
  23.     doversion();
  24.  
  25. char *Ax25states[] = {
  26.     "Disconnected",
  27.     "Conn pending",
  28.     "Disc pending",
  29.     "Connected",
  30.     "Recovery",
  31.     "Frame Reject",
  32. };
  33.  
  34. /* Ascii explanations for the disconnect reasons listed in lapb.h under
  35.  * "reason" in ax25_cb
  36.  */
  37. char *Axreasons[] = {
  38.     "Normal",
  39.     "DM received",
  40.     "Timeout"
  41. };
  42.  
  43. static struct cmds axcmds[] = {
  44.     "digipeat",    dodigipeat,    0, 0, NULLCHAR,
  45.     "irtt",        doaxirtt,    0, 0, NULLCHAR,
  46.     "maxframe",    domaxframe,    0, 0, NULLCHAR,
  47.     "mycall",    domycall,    0, 0, NULLCHAR,
  48.     "paclen",    dopaclen,    0, 0, NULLCHAR,
  49.     "pthresh",    dopthresh,    0, 0, NULLCHAR,
  50.     "reset",    doaxreset,    0, 2, "ax25 reset <axcb>",
  51.     "retry",    don2,        0, 0, NULLCHAR,
  52.     "route",    doaxroute,    0, 0, NULLCHAR,
  53.     "status",    doaxstat,    0, 0, NULLCHAR,
  54.     "t3",        dot3,        0, 0, NULLCHAR,
  55.     "version",    doversion,    0, 0, NULLCHAR,
  56.     "window",    doaxwindow,    0, 0, NULLCHAR,
  57.     NULLCHAR,    NULLFP,        0, 0, "ax25 subcommands: digipeat maxframe mycall paclen pthresh reset retry status\n\tt1 t3 window",
  58. };
  59. /* Multiplexer for top-level ax25 command */
  60. doax25(argc,argv,envp)
  61. int argc;
  62. char *argv[];
  63. void *envp;
  64. {
  65.     return subcmd(axcmds,argc,argv,envp);
  66. }
  67.  
  68. static
  69. doaxreset(argc,argv)
  70. int argc;
  71. char *argv[];
  72. {
  73.     struct ax25_cb *axp;
  74.  
  75.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  76.     if(!ax25val(axp)){
  77.         printf(Notval);
  78.         return 1;
  79.     }
  80.     reset_ax25(axp);
  81.     return 0;
  82. }
  83.  
  84. /* Display AX.25 link level control blocks */
  85. static
  86. doaxstat(argc,argv)
  87. int argc;
  88. char *argv[];
  89. {
  90.     register int i;
  91.     register struct ax25_cb *axp;
  92.     char tmp[10];
  93.  
  94.     if(argc < 2){
  95.         printf("    &AXB Snd-Q   Rcv-Q   Remote    State\n");
  96.         for(i=0;i<NHASH;i++){
  97.             for(axp = Ax25_cb[i];axp != NULLAX25; axp = axp->next){
  98.                 pax25(tmp,&axp->remote);
  99.                 printf("%8lx %-8d%-8d%-10s%s\n",
  100.                     (long)axp,
  101.                     len_q(axp->txq),len_mbuf(axp->rxq),
  102.                     tmp,Ax25states[axp->state]);
  103.             }
  104.         }
  105.         return 0;
  106.     }
  107.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  108.     if(!ax25val(axp)){
  109.         printf(Notval);
  110.         return 1;
  111.     }
  112.     st_ax25(axp);
  113.     return 0;
  114. }
  115. /* Dump one control block */
  116. void
  117. st_ax25(axp)
  118. register struct ax25_cb *axp;
  119. {
  120.     char tmp[10];
  121.  
  122.     if(axp == NULLAX25)
  123.         return;
  124.     printf("&AXB Remote   RB V(S) V(R) Unack P Retry State\n");
  125.     pax25(tmp,&axp->remote);
  126.     printf("%4x %-9s",(int)axp,tmp);
  127.     putchar(axp->flags.rejsent ? 'R' : ' ');
  128.     putchar(axp->flags.remotebusy ? 'B' : ' ');
  129.     printf(" %4d %4d",axp->vs,axp->vr);
  130.     printf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
  131.     printf(" %02u/%02u",axp->retries,axp->n2);
  132.     printf(" %s\n",Ax25states[axp->state]);
  133.  
  134.     printf("SRT = %lu ",axp->srt * MSPTICK);
  135.     printf("T1: ");
  136.     if(run_timer(&axp->t1))
  137.         printf("%lu",read_timer(&axp->t1) * MSPTICK);
  138.     else
  139.         printf("stop");
  140.     printf("/%lu ms; ",dur_timer(&axp->t1) * MSPTICK);
  141.  
  142.     printf("T3: ");
  143.     if(run_timer(&axp->t3))
  144.         printf("%lu",read_timer(&axp->t3) * MSPTICK);
  145.     else
  146.         printf("stop");
  147.     printf("/%lu ms\n",dur_timer(&axp->t3) * MSPTICK);
  148.  
  149. }
  150.  
  151. /* Display or change our AX.25 address */
  152. static
  153. domycall(argc,argv)
  154. int argc;
  155. char *argv[];
  156. {
  157.     char buf[15];
  158.  
  159.     if(argc < 2){
  160.         pax25(buf,&Mycall);
  161.         printf("%s\n",buf);
  162.         return 0;
  163.     }
  164.     if(setcall(&Mycall,argv[1]) == -1)
  165.         return -1;
  166.     Mycall.ssid |= E;
  167.     return 0;
  168. }
  169.  
  170. /* Control AX.25 digipeating */
  171. static
  172. dodigipeat(argc,argv)
  173. int argc;
  174. char *argv[];
  175. {
  176.     if(argc == 1) {
  177.         printf("digipeat %s\n",Digipeat ? "on" : "off");
  178.     } else {
  179.         if(strcmp(argv[1],"on") == 0)
  180.             Digipeat = 1;
  181.         else
  182.             Digipeat = 0;
  183.     }
  184.     return 0;
  185. }
  186. static
  187. doversion(argc,argv)
  188. int argc;
  189. char *argv[];
  190. {
  191.     if(argc == 1){
  192.         printf("AX25 version %s\n",Axversion == V1 ? "V1" : "V2");
  193.         return 0;
  194.     }
  195.     if(strchr(argv[1],'1') != NULLCHAR)
  196.         Axversion = V1;
  197.     else if(strchr(argv[1],'2') != NULLCHAR)
  198.         Axversion = V2;
  199.     else
  200.         return -1;
  201.     return 0;
  202. }
  203.  
  204. static
  205. doaxirtt(argc,argv)
  206. int argc;
  207. char *argv[];
  208. {
  209.     if(argc == 1){
  210.         printf("AX25 initial round trip time: %lu ms\n",Axirtt*MSPTICK);
  211.     } else {
  212.         Axirtt = atol(argv[1]) / MSPTICK;
  213.     }
  214.     return 0;
  215. }
  216.  
  217. /* Set idle timer */
  218. static
  219. dot3(argc,argv)
  220. int argc;
  221. char *argv[];
  222. {
  223.     if(argc == 1) {
  224.         printf("T3 %lu ms\n",(long)T3init * MSPTICK);
  225.     } else {
  226.         T3init = atol(argv[1]) / MSPTICK;
  227.     }
  228.     return 0;
  229. }
  230.  
  231. /* Set retry limit count */
  232. static
  233. don2(argc,argv)
  234. int argc;
  235. char *argv[];
  236. {
  237.     if(argc == 1) {
  238.         printf("Retry %u\n",N2);
  239.     } else {
  240.         N2 = atoi(argv[1]);
  241.     }
  242.     return 0;
  243. }
  244.  
  245. /* Set maximum number of frames that will be allowed in flight */
  246. static
  247. domaxframe(argc,argv)
  248. int argc;
  249. char *argv[];
  250. {
  251.     if(argc == 1) {
  252.         printf("Maxframe %u\n",Maxframe);
  253.     } else {
  254.         Maxframe = atoi(argv[1]);
  255.     }
  256.     return 0;
  257. }
  258.  
  259. /* Set maximum length of I-frame data field */
  260. static
  261. dopaclen(argc,argv)
  262. int argc;
  263. char *argv[];
  264. {
  265.     if(argc == 1) {
  266.         printf("Paclen %u\n",Paclen);
  267.     } else {
  268.         Paclen = atoi(argv[1]);
  269.     }
  270.     return 0;
  271. }
  272. /* Set size of I-frame above which polls will be sent after a timeout */
  273. static
  274. dopthresh(argc,argv)
  275. int argc;
  276. char *argv[];
  277. {
  278.     if(argc == 1) {
  279.         printf("Pthresh %u\n",Pthresh);
  280.     } else {
  281.         Pthresh = atoi(argv[1]);
  282.     }
  283.     return 0;
  284. }
  285.  
  286. /* Set high water mark on receive queue that triggers RNR */
  287. static
  288. doaxwindow(argc,argv)
  289. int argc;
  290. char *argv[];
  291. {
  292.     if(argc == 1) {
  293.         printf("Axwindow %u\n",Axwindow);
  294.     } else {
  295.         Axwindow = atoi(argv[1]);
  296.     }
  297.     return 0;
  298. }
  299. /* End of ax25 subcommands */
  300.  
  301. /* Initiate interactive AX.25 connect to remote station */
  302. doconnect(argc,argv)
  303. int argc;
  304. char *argv[];
  305.  {
  306.     struct session *sp;
  307.     int s;
  308.     struct sockaddr_ax fsocket;
  309.     struct mbuf *bp;
  310.     char *cp;
  311.  
  312.     /* Allocate a session descriptor */
  313.     if((sp = newsession(argv[2],AX25TNC)) == NULLSESSION){
  314.         printf("Too many sessions\n");
  315.         return 1;
  316.     }
  317.     Current = sp;
  318.     Mode = CONV_MODE;
  319.     sp->cb.ax25 = (struct ax25tnc *)calloc(1,sizeof(struct ax25tnc));
  320.     sp->cb.ax25->session = sp;
  321.     sp->cb.ax25->output = Curproc;
  322.  
  323.     if((s = sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
  324.         freesession(sp);
  325.         printf("Can't create socket\n");
  326.         return 1;
  327.     }
  328.     fsocket.sax_family = AF_AX25;
  329.     setcall(&fsocket.ax25_addr,argv[2]);
  330.     strncpy(fsocket.iface,argv[1],ILEN);
  331.     printf("Trying %s...\n",psocket((struct sockaddr *)&fsocket));
  332.     if(connect(s,(char *)&fsocket,SOCKSIZE) == -1){
  333.         printf("AX25 session %u failed: %s errno %d\n",
  334.          (unsigned)(sp-Sessions),sockerr(s),errno);
  335.         close_s(s);
  336.         free((char *)sp->cb.ax25);
  337.         freesession(sp);
  338.         return 1;
  339.     }
  340.     printf("AX25 session %u connected to %s\n",
  341.         (unsigned)(sp-Sessions),sp->name);
  342.     sp->cb.ax25->output = Curproc;
  343.     sp->cb.ax25->input = newproc("ax_in",1024,ax_in,0,sp->cb.ax25,NULL);
  344.     for(;;){
  345.         while(sp->input == NULLBUF)
  346.             pwait(&sp->input);
  347.  
  348.         bp = dequeue(&sp->input);
  349.  
  350.         /* If we're recording, record it */
  351.         if(sp->record != NULLFILE)
  352.             write_p(sp->record,bp);
  353.  
  354.         /* Get rid of the trailing newline */
  355.         if((cp = strchr(bp->data,'\n')) != NULLCHAR){
  356.             *cp = '\0';
  357.             bp->cnt--;
  358.         }
  359.         if(send_mbuf(s,bp,0,NULLCHAR,0) == -1)
  360.             break;
  361.     }
  362.     killproc(sp->cb.ax25->input);
  363.     close_s(s);
  364.     free((char *)sp->cb.ax25);
  365.     freesession(sp);
  366.     return 0;
  367. }
  368. /* Display and modify AX.25 routing table */
  369. static int
  370. doaxroute(argc,argv)
  371. int argc;
  372. char *argv[];
  373. {
  374.     char buf[30];
  375.     int i,j,ndigis;
  376.     register struct ax_route *axr;
  377.     struct ax25_addr target,digis[MAXDIGIS];
  378.  
  379.     if(argc < 2){
  380.         printf("Target    Type   Digipeaters\n");
  381.         for(i=0;i<NAXROUTE;i++){
  382.             for(axr = Ax_routes[i];axr != NULLAXR;axr = axr->next){
  383.                 pax25(buf,&axr->target);
  384.                 printf("%-10s%-6s",buf,
  385.                  axr->type == AX_LOCAL ? "Local":"Auto");
  386.                 for(j=0;j<axr->ndigis;j++){
  387.                     pax25(buf,&axr->digis[j]);
  388.                     printf(" %s",buf);
  389.                 }
  390.                 printf("\n");
  391.             }
  392.         }
  393.         return 0;
  394.     }
  395.     if(argc < 3){
  396.         printf("Usage: ax25 route add <target> [digis...]\n");
  397.         printf("       ax25 route drop <target>\n");
  398.         return 1;
  399.     }
  400.     if(setcall(&target,argv[2]) == -1){
  401.         printf("Bad target %s\n",argv[2]);
  402.         return 1;
  403.     }
  404.     switch(argv[1][0]){
  405.     case 'a':    /* Add route */
  406.         if(argc < 3){
  407.             printf("Usage: ax25 route add <target> [digis...]\n");
  408.             return 1;
  409.         }
  410.         ndigis = argc - 3;
  411.         for(i=0;i<ndigis;i++){
  412.             if(setcall(&digis[i],argv[i+3]) == -1){
  413.                 printf("Bad digipeater %s\n",argv[i+3]);
  414.                 return 1;
  415.             }
  416.         }
  417.         if(ax_add(&target,AX_LOCAL,&digis[0],ndigis) == NULLAXR){
  418.             printf("Failed\n");
  419.             return 1;
  420.         }
  421.         break;
  422.     case 'd':    /* Drop route */
  423.         if(ax_drop(&target) == -1){
  424.             printf("Not in table\n");
  425.             return 1;
  426.         }
  427.         break;
  428.     default:
  429.         printf("Unknown command %s\n",argv[1]);
  430.         return 1;
  431.     }
  432.     return 0;
  433. }
  434. void
  435. ax_upload(unused,sp)
  436. int unused;
  437. struct session *sp;
  438. {
  439.     struct mbuf *bp;
  440.     char *cp;
  441.     int c;
  442.  
  443.     for(;;){
  444.         bp = alloc_mbuf(BUFSIZ);
  445.         cp = bp->data;
  446.         while(bp->cnt < BUFSIZ){
  447.             if((c = getc(sp->upload)) == EOF)
  448.                 break;
  449.             if(c == '\r')
  450.                 continue;
  451.             if(c == '\n')
  452.                 c = '\r';
  453.             *cp++ = c;
  454.             bp->cnt++;
  455.         }
  456.         if(bp->cnt == 0){
  457.             free_p(bp);
  458.             break;
  459.         } else if(send_mbuf(sp->s,bp,0,NULLCHAR,0) == -1)
  460.             break;
  461.     }
  462.     fclose(sp->upload);
  463.     sp->cb.ax25->upload = NULLPROC;
  464. }
  465. /* AX.25 TNC receive process */
  466. void
  467. ax_in(unused,tnc)
  468. int unused;
  469. struct ax25tnc *tnc;
  470. {
  471.     char c;
  472.     struct session *sp;
  473.     char *cp;
  474.     struct mbuf *bp;
  475.     int s;
  476.  
  477.     sp = tnc->session;
  478.     s = sp->s;
  479.  
  480.     for(;;){
  481.         if(recv_mbuf(s,&bp,0,0,NULLCHAR,0) == -1)
  482.             break;
  483.         while(pullup(&bp,&c,1) == 1){
  484.             /* Suspend output if we're not current */
  485.             while(Current != sp || Mode != CONV_MODE)
  486.                 pwait(sp);
  487.  
  488.             putchar(c);
  489.             if(c == '\r')
  490.                 putchar('\n');
  491.  
  492.             if(sp->record != NULLFILE){
  493.                 putc(c,sp->record);
  494.                 if(c == '\r')
  495.                     putc('\r',sp->record);
  496.             }
  497.         }
  498.     }
  499.     /* Close seen from remote host */
  500.     cp = sockerr(s);
  501.     printf("AX25 session %u closed: %s\n", (unsigned)(sp - Sessions),
  502.      cp != NULLCHAR ? cp : "EOF");
  503.     close_s(s);
  504.     tnc->input = NULLPROC;
  505.     killproc(tnc->output);
  506.     free((char *)tnc);
  507.     freesession(sp);
  508. }
  509.  
  510.